/* ** por compatibilidad se omiten tildes **
================================================================================
 TRABAJO PRACTICO 3 - System Programming - ORGANIZACION DE COMPUTADOR II - FCEN
================================================================================
  definicion de funciones del scheduler
*/

#include "screen.h"
#include "colors.h"
#include "sched.h"

int modo_debug = 0;

ca pantalla_aux[50][80];

void print(const char * text, unsigned int x, unsigned int y, unsigned short attr) {
    ca (*p)[VIDEO_COLS] = (ca (*)[VIDEO_COLS]) VIDEO;
    int i;
    for (i = 0; text[i] != 0; i++) {
        p[x][y].c = (unsigned char) text[i];
        p[x][y].a = (unsigned char) attr;
        y++;
        if (y == VIDEO_COLS) {
            y = 0;
            x++;
        }
    }
}

void print_hex(unsigned int numero, int size, unsigned int x, unsigned int y, unsigned char attr) {
    ca (*p)[VIDEO_COLS] = (ca (*)[VIDEO_COLS]) VIDEO; // magia
    int i;
    char hexa[8];
    char letras[16] = "0123456789ABCDEF";
    hexa[0] = letras[ ( numero & 0x0000000F ) >> 0  ];
    hexa[1] = letras[ ( numero & 0x000000F0 ) >> 4  ];
    hexa[2] = letras[ ( numero & 0x00000F00 ) >> 8  ];
    hexa[3] = letras[ ( numero & 0x0000F000 ) >> 12 ];
    hexa[4] = letras[ ( numero & 0x000F0000 ) >> 16 ];
    hexa[5] = letras[ ( numero & 0x00F00000 ) >> 20 ];
    hexa[6] = letras[ ( numero & 0x0F000000 ) >> 24 ];
    hexa[7] = letras[ ( numero & 0xF0000000 ) >> 28 ];
    for(i = 0; i < size; i++) {
        p[x][y+size-i-1].c = hexa[i];
        p[x][y+size-i-1].a = attr;
    }
}

void pantalla_inicial(){
    ca (*p)[VIDEO_COLS] = (ca (*)[VIDEO_COLS]) VIDEO;
    p = p;
    int i,j;
    for (i = 0; i < 50; i++){
        for (j = 0; j < 80; j++){
            p[i][j].c = 0;
            if(!i){                                         //barra negra arriba
                p[i][j].a =C_BG_BLACK;
            }
            else if(!j && i< 45){                           //barra roja de la izquierda 
                p[i][j].a = C_BG_RED;
            }
            else if(j==79 && i< 45){                        //barra azul de la derecha 
                p[i][j].a = C_BG_BLUE;
            }
            else if(i>=45){
        
                if(j>=34 && j<=39){
                    p[i][j].a = C_BG_RED;                   //cuadrado rojo de puntuacion
                }
                else{
                    if(j>=40 && j<=45){
                        p[i][j].a = C_BG_BLUE;                   //cuadrado rojo de puntuacion
                    }
                    else p[i][j].a = C_BG_BLACK;
                }
                
            }
            else{
                p[i][j].a = C_BG_GREEN;
            }
        }
    }
    char* text1;
    print_hex(20,2,47,30,C_FG_WHITE);
    print_hex(20,2,47,48,C_FG_WHITE);
    text1 = "0";
    print((char*)text1, 47, 36, C_FG_WHITE);
    print((char*)text1, 47, 43, C_FG_WHITE);
    text1 = "1 2 3 4 5 6 7 8";
    print((char*)text1, 46, 4, C_FG_WHITE);
    print((char*)text1, 46, 60, C_FG_WHITE);
    text1 = "X X X X X X X X";
    print((char*)text1, 48, 4, C_FG_RED + C_BG_BLACK);
    print((char*)text1, 48, 60, C_FG_BLUE + C_BG_BLACK);
}

void pantalla_debug(){
    ca (*p)[VIDEO_COLS] = (ca (*)[VIDEO_COLS]) VIDEO;
    tss* actual;
    if (j_actual == 'A'){
        actual = &tss_zombisA[indice_A];
    }
    else{
        actual = &tss_zombisB[indice_B];
    }
    int i,j;
    for (i = 7; i < 43; i++){
        for (j = 25; j < 55; j++){
            p[i][j].c = 0;
            if(i==7 || i==42 || j==25 || j==54){                                       
                p[i][j].a =C_BG_BLACK;
            }
            else if(i==8){
                if(j_actual == 'A'){
                    p[i][j].a = C_BG_RED;
                }                           
                else{
                    p[i][j].a = C_BG_BLUE;
                }
            }
            else                   
                p[i][j].a = C_BG_LIGHT_GREY;        
        }
    }
    char* text1="eax"; 
    print(text1, 10, 27, C_BG_LIGHT_GREY);
    print_hex(actual->eax,8,10,31,C_BG_LIGHT_GREY);
    text1="ebx"; 
    print(text1, 12, 27, C_BG_LIGHT_GREY);
    print_hex(actual->ebx,8,12,31,C_BG_LIGHT_GREY);
    text1="ecx"; 
    print(text1, 14, 27, C_BG_LIGHT_GREY);
    print_hex(actual->ecx,8,14,31,C_BG_LIGHT_GREY);
    text1="edx"; 
    print(text1, 16, 27, C_BG_LIGHT_GREY);
    print_hex(actual->edx,8,16,31,C_BG_LIGHT_GREY);
    text1="esi"; 
    print(text1, 18, 27, C_BG_LIGHT_GREY);
    print_hex(actual->esi,8,18,31,C_BG_LIGHT_GREY);
    text1="edi"; 
    print(text1, 20, 27, C_BG_LIGHT_GREY);
    print_hex(actual->edi,8,20,31,C_BG_LIGHT_GREY);
    text1="ebp"; 
    print(text1, 22, 27, C_BG_LIGHT_GREY);
    print_hex(actual->ebp,8,22,31,C_BG_LIGHT_GREY);
    text1="esp"; 
    print(text1, 24, 27, C_BG_LIGHT_GREY);
    print_hex(actual->esp,8,24,31,C_BG_LIGHT_GREY);
    text1="eip"; 
    print(text1, 26, 27, C_BG_LIGHT_GREY);
    print_hex(actual->eip,8,26,31,C_BG_LIGHT_GREY);
    text1="cs"; 
    print(text1, 28, 28, C_BG_LIGHT_GREY);
    print_hex(actual->cs,8,28,31,C_BG_LIGHT_GREY);
    text1="ds"; 
    print(text1, 30, 28, C_BG_LIGHT_GREY);
    print_hex(actual->ds,8,30,31,C_BG_LIGHT_GREY);
    text1="es"; 
    print(text1, 32, 28, C_BG_LIGHT_GREY);
    print_hex(actual->es,8,32,31,C_BG_LIGHT_GREY);
    text1="fs"; 
    print(text1, 34, 28, C_BG_LIGHT_GREY);
    print_hex(actual->fs,8,34,31,C_BG_LIGHT_GREY);
    text1="gs"; 
    print(text1, 36, 28, C_BG_LIGHT_GREY);
    print_hex(actual->gs,8,36,31,C_BG_LIGHT_GREY);
    text1="ss"; 
    print(text1, 38, 28, C_BG_LIGHT_GREY);
    print_hex(actual->ss,8,38,31,C_BG_LIGHT_GREY);
    text1="eflags"; 
    print(text1, 40, 28, C_BG_LIGHT_GREY);
    print_hex(actual->eflags,8,40,35,C_BG_LIGHT_GREY);
    text1="cr0"; 
    print(text1, 10, 41, C_BG_LIGHT_GREY);
    print_hex(rcr0(),8,10,45,C_BG_LIGHT_GREY);
    text1="cr2"; //que paso aca??
    print(text1, 12, 41, C_BG_LIGHT_GREY);
    print_hex(rcr2(),8,12,45,C_BG_LIGHT_GREY);
    text1="cr3"; 
    print(text1, 14, 41, C_BG_LIGHT_GREY);
    print_hex(rcr3(),8,14,45,C_BG_LIGHT_GREY);
    text1="cr4"; 
    print(text1, 16, 41, C_BG_LIGHT_GREY);
    print_hex(rcr3(),8,16,45,C_BG_LIGHT_GREY);
    text1="stack"; 
    print(text1, 27, 41, C_BG_LIGHT_GREY);
    unsigned int* puntero = (unsigned int*) actual->esp;
    print_hex(*(puntero+1),8,28,41,C_BG_LIGHT_GREY);
    print_hex(*(puntero+2),8,29,41,C_BG_LIGHT_GREY);
    print_hex(*(puntero+3),8,30,41,C_BG_LIGHT_GREY);
    print_hex(*(puntero+4),8,31,41,C_BG_LIGHT_GREY);

    char* text = "Zombie A";
    if (j_actual=='A'){
        print(text, 8, 27, C_BG_RED + C_FG_WHITE);
        switch(tiposA[indice_A]){
            case 'M':
                text = "Mago";
                break;
            case 'G':
                text = "Guerrero";
                break;
            default:
                text = "Clerigo";
                break;
        }
    print(text, 8, 36, C_BG_RED + C_FG_WHITE);
    }
    else{
        text = "Zombie B";
        print(text, 8, 27, C_BG_BLUE + C_FG_WHITE);
        switch(tiposB[indice_B]){
            case 'M':
                text = "Mago";
                break;
            case 'G':
                text = "Guerrero";
                break;
            default:
                text = "Clerigo";
                break;
        }
        print(text, 8, 36, C_BG_BLUE + C_FG_WHITE);
    }
    
}


void imprimir_como_ascii(unsigned int scan_code){
    char letra;
    switch(scan_code){
        case 0x11:
            letra = 'w';
            break;
        case 0x15:
            letra = 'y';
            break;
        case 0x17:
            letra = 'i';
            break;
        case 0x1e:
            letra = 'a';
            break;
        case 0x1f:
            letra = 's';
            break;
        case 0x20:
            letra = 'd';
            break;
        case 0x24:
            letra = 'j';
            break;
        case 0x25:
            letra = 'k';
            break;
        case 0x26:
            letra = 'l';
            break;
        case 0x2a:
            letra = 0x4b;
            break;
        case 0x36:
            letra = 0x56;
            break;
    }
    if (!(letra == 0x56 || letra == 0x4b)){
        char text[2];
        text[0] = letra;
        text[1] = 0; 
        print((char*)text, 0, 79, 0x20);
    }
}

void atender_teclado(unsigned int scan_code){
    if (frozen == 0){
        switch(scan_code){
            case 0x11:
                game_jugador_mover('A',-1);
                break;
            case 0x17:
                game_jugador_mover('B',-1);
                break;
            case 0x1f:
                game_jugador_mover('A',1);
                break;
            case 0x25:
                game_jugador_mover('B',1);
                break;
            case 0x1e:
                game_zombie_rotar('A',-1);
                break;
            case 0x20:
                game_zombie_rotar('A',1);
                break;
            case 0x24:
                game_zombie_rotar('B',-1);
                break;
            case 0x26:
                game_zombie_rotar('B',1);
                break;
            case 0x15:
                modo_debug = 1;
                break;
            case 0x2a:
                game_lanzar_zombi('A');
                break;
            case 0x36:
                game_lanzar_zombi('B');
                break;
            default:
                break;
        }
    }
    else{
        if(scan_code == 0x15){
            frozen = 0;
            cargar_pantalla();
        }
    }        
}

void guardar_pantalla(){
    ca (*p)[VIDEO_COLS] = (ca (*)[VIDEO_COLS]) VIDEO;
    int i,j;
    for (i = 0; i < 50; i++){
        for (j = 0; j < 80; j++){
            pantalla_aux[i][j].c = p[i][j].c;
            pantalla_aux[i][j].a = p[i][j].a;
        }
    }
}

void cargar_pantalla(){
    ca (*p)[VIDEO_COLS] = (ca (*)[VIDEO_COLS]) VIDEO;
    int i,j;
    for (i = 0; i < 50; i++){
        for (j = 0; j < 80; j++){
            p[i][j].c = pantalla_aux[i][j].c;
            p[i][j].a = pantalla_aux[i][j].a;
        }
    }
}

void atender_debug(){
    ca (*p)[VIDEO_COLS] = (ca (*)[VIDEO_COLS]) VIDEO;
    int x,y;
    if(j_actual == 'A'){
        x = posicionesA[2*indice_A];
        y = posicionesA[2*indice_A+1];
    }
    else{
        x = posicionesB[2*indice_B];
        y = posicionesB[2*indice_B+1];
    }
    p[x][y].c = 'X';
    p[x][y].a = C_BG_GREEN + C_FG_RED;
    if (modo_debug == 1){
        guardar_pantalla();
        pantalla_debug();
        frozen = 1;
    }
}

void up_relojes(){
    int i;
    char* cruz = "X";
    for (i = 0; i < 8; i++){
        if (zombisAvivos[i] == 0){
            print(cruz,48,4+2*i,C_FG_RED+C_FG_BLACK);
        }
        if (zombisBvivos[i] == 0){ 
            print(cruz,48,60+2*i,C_FG_BLUE+C_FG_BLACK);
        }
    }
    char* clock = "|/-\\";
    char text[2] = {0,0};
    if (j_actual == 'A'){
        relojesA[indice_A] = (relojesA[indice_A]+1)%4;
        text[0] = clock[relojesA[indice_A]];
        print(text,48,4+2*indice_A,C_FG_WHITE + C_FG_BLACK);
    }
    else if (j_actual == 'B'){
        relojesB[indice_B] = (relojesB[indice_B]+1)%4;
        text[0] = clock[relojesB[indice_B]];
        print(text,48,60+2*indice_B,C_FG_WHITE + C_FG_BLACK);
    }
}